package 
{
   import _effx.visual.PerlinField;
   
   import com.bit101.components.CheckBox;
   import com.bit101.components.HUISlider;
   import com.bit101.components.List;
   
   import flash.display.Bitmap;
   import flash.display.MovieClip;
   import flash.display.StageAlign;
   import flash.display.StageScaleMode;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.text.TextField;
   
   /**
    * Perlin Noise
    * @author boy, cjboy1984@gmail.com
    */
   public class PerlinNoiseMain extends MovieClip
   {
      // fla
      public var tfOctaves:TextField;
      // UI
      public var channelBox1:CheckBox;
      public var channelBox2:CheckBox;
      public var channelBox3:CheckBox;
      public var vecList:List;
      public var xSlider:HUISlider;
      public var ySlider:HUISlider;
      
      // perlin
      private var perlinNoz:PerlinField = new PerlinField(217, 289); // <-- very important
      
      public function PerlinNoiseMain()
      {
         addEventListener(Event.ADDED_TO_STAGE, onAdd);
         addEventListener(Event.REMOVED_FROM_STAGE, onRemove);
      }
      
      // --------------------- LINE ---------------------
      
      public function startEfx():void
      {
         addEventListener(Event.ENTER_FRAME, updateAll);
      }
      
      public function stopEfx():void
      {
         removeEventListener(Event.ENTER_FRAME, updateAll);
      }
      
      // ################### protected ##################
      
      // #################### private ###################
      
      
      private function onAdd(e:Event):void
      {
         // basic
         stage.align = StageAlign.TOP_LEFT;
         stage.scaleMode = StageScaleMode.NO_SCALE;
         
         initNoise();
         initUI();
         startEfx();
      }
      
      private function onRemove(e:Event):void
      {
         removeEventListener(Event.ENTER_FRAME, updateAll);
      }
      
      // ________________________________________________
      //                                             init
      
      private function initNoise():void
      {
         perlinNoz.channels = 1 | 2 | 4;
         perlinNoz.numOctaves = 2;
         
         var bmp:Bitmap = new Bitmap(perlinNoz.bitmapData);
         addChild(bmp);
      }
      
      private function initUI():void
      {
         // channel
         channelBox1 = new CheckBox(this, 237, 34, 'Red (1)', onChannelChange);
         channelBox2 = new CheckBox(this, 237, 56, 'Green (2)', onChannelChange);
         channelBox3 = new CheckBox(this, 237, 78, 'Blue (4)', onChannelChange);
         updateChannelView();
         
         // octaves
         tfOctaves.restrict = '0123456789';
         tfOctaves.addEventListener(Event.CHANGE, onOctaveChange);
         updateOctavesView();
         
         // velocity of octaves
         vecList = new List(this, 229, 187);
         vecList.addEventListener(Event.SELECT, onListSelect);
         vecList.setSize(55, 90);
         xSlider = new HUISlider(this, 289, 212, '', onHSliderChange);
         xSlider.setSize(132, 18);
         xSlider.maximum = +10;
         xSlider.minimum = -10;
         xSlider.tick = 1;
         ySlider = new HUISlider(this, 289, 252, '', onHSliderChange);
         ySlider.setSize(132, 18);
         ySlider.maximum = +10;
         ySlider.minimum = -10;
         ySlider.tick = 1;
         updateVecView();
      }
      
      // ________________________________________________
      //                                               UI
      
      private function onChannelChange(e:MouseEvent):void
      {
         var btn:CheckBox = CheckBox(e.currentTarget);
         var orValue:uint;
         switch(btn)
         {
            case channelBox1:
               orValue = 1;
               break;
            case channelBox2:
               orValue = 2;
               break;
            case channelBox3:
               orValue = 4;
               break;
         }
         
         if (btn.selected)
         {
            perlinNoz.channels |= orValue;
         }
         else
         {
            perlinNoz.channels ^= orValue;
         }
         
         updateChannelView();
      }
      
      private function updateChannelView():void
      {
         // red
         if (perlinNoz.channels & 1)
         {
            channelBox1.selected = true;
         }
         else
         {
            channelBox1.selected = false;
         }
         
         // green
         if (perlinNoz.channels & 2)
         {
            channelBox2.selected = true;
         }
         else
         {
            channelBox2.selected = false;
         }
         
         // blue
         if (perlinNoz.channels & 4)
         {
            channelBox3.selected = true;
         }
         else
         {
            channelBox3.selected = false;
         }
      }
      
      // --------------------- LINE ---------------------
      
      private function onOctaveChange(e:Event):void
      {
         var oct:uint = uint(tfOctaves.text);
         
         if (tfOctaves.text == '')
         {
            oct = 0;
            tfOctaves.text = '0';
            tfOctaves.setSelection(0, tfOctaves.length);
         }
         
         perlinNoz.numOctaves = oct;
         updateVecView();
      }
      
      private function updateOctavesView():void
      {
         tfOctaves.text = String(perlinNoz.numOctaves);
      }
      
      // --------------------- LINE ---------------------
      
      private function onListSelect(e:Event):void
      {
         if (vecList.selectedIndex < 0 || vecList.selectedIndex >= perlinNoz.velocityPool.length) return;
         
         xSlider.value = perlinNoz.velocityPool[vecList.selectedIndex].x;
         ySlider.value = perlinNoz.velocityPool[vecList.selectedIndex].y;
      }
      
      private function onHSliderChange(e:Event):void
      {
         var btn:HUISlider = HUISlider(e.currentTarget);
         if (btn == xSlider)
         {
            perlinNoz.velocityPool[vecList.selectedIndex].x = btn.value;
         }
         else if (btn == ySlider)
         {
            perlinNoz.velocityPool[vecList.selectedIndex].y = btn.value;
         }
      }
      
      private function updateVecView():void
      {
         vecList.removeAll();
         
         if (perlinNoz.velocityPool.length > 0)
         {
            vecList.enabled = true;
            for (var i:int = 0; i < perlinNoz.velocityPool.length; ++i) 
            {
               var lb:String = 'vec[' + String(i) + ']';
               vecList.addItem({label:lb});
            }
            vecList.selectedIndex = 0;
            
            xSlider.enabled = true;
            ySlider.enabled = true;
            xSlider.value = perlinNoz.velocityPool[vecList.selectedIndex].x;
            ySlider.value = perlinNoz.velocityPool[vecList.selectedIndex].y;
         }
         else
         {
            vecList.enabled = false;
            vecList.selectedIndex = -1;
            
            xSlider.enabled = false;
            ySlider.enabled = false;
         }
      }
      
      // ________________________________________________
      //                                      enter frame
      
      private function updateAll(e:Event):void
      {
         perlinNoz.update();
      }
      
      // --------------------- LINE ---------------------
      
   }
   
}